package com.gitee.huanminabc.jlambda_sql.warapper;

import com.gitee.huanminabc.jlambda_sql.base.SqlFun;
import lombok.extern.slf4j.Slf4j;

/**
 * 查询条件构造器
 *
 * @Author: huanmin
 * @Date: 2025/4/5 22:33
 * @Version: 1.0
 * @Description: 文件作用详细描述....
 */
@Slf4j
public class LambdaQueryWrapper<T> extends DefaultWhereWrapper<T, LambdaQueryWrapper<T>> {
    private String orderBySql;
    private String groupBySql;
    private String havingSql;
    private String limitSql;

    //关联主表, 这个实体用于接收查询结果的,无须和数据库表完全对应
    public static <T> LambdaQueryWrapper<T> create(Class<T> entity) {
        return new LambdaQueryWrapper<>(entity, "t1");
    }

    public static <T> LambdaQueryWrapper<T> create(Class<T> entity, String alias) {
        return new LambdaQueryWrapper<>(entity, alias);
    }

    //默认别名 t1
    private LambdaQueryWrapper(Class<T> entityClass, String alias) {
        super(LambdaWrapper.create(entityClass));
        typedThis.SELECT().S_COLUMN().FROM();
        if (!alias.equals("t1")) {
            typedThis.TABLE_ALIAS(alias);
        } else {
            typedThis.TABLE();
        }
        typedThis.WHERE();
    }

    //设置列  表的别名默认是t1
    public final LambdaQueryWrapper<T> COLUMN(String... columns) {
        typedThis.SQL().clearSelectColumns();//清理
        for (String column : columns) {
            SQL().addSelectColumn(column);
        }
        return children;
    }

    @SafeVarargs
    public final LambdaQueryWrapper<T> COLUMN(SqlFun<T, ?>... columns) {
        typedThis.SQL().clearSelectColumns();//清理
        for (SqlFun<T, ?> column : columns) {
            typedThis.getFunFieldName(column, (sqlColumn) -> {
                SQL().addSelectColumn(sqlColumn.getTableName(), sqlColumn.getColumnName());
            });
        }
        return children;
    }


    //order by
    public final LambdaQueryWrapper<T> ORDER_BY_ASC(SqlFun<T, ?>... columns) {
        StringBuilder stringBuilder = new StringBuilder("ORDER BY ");

        for (SqlFun<T, ?> column : columns) {
            typedThis.getFunFieldName(column, sqlColumn -> {
                stringBuilder.append(sqlColumn.getTableName()).append(".").append(sqlColumn.getColumnName()).append(",");
            });
        }

        orderBySql = stringBuilder.substring(0, stringBuilder.length() - 1) + " ASC";
        return children;
    }

    public final LambdaQueryWrapper<T> ORDER_BY_ASC(boolean condition, SqlFun<T, ?>... columns) {
        if (condition) {
            ORDER_BY_ASC(columns);
        }
        return children;
    }

    public final LambdaQueryWrapper<T> ORDER_BY_DESC(SqlFun<T, ?>... columns) {
        StringBuilder stringBuilder = new StringBuilder("ORDER BY ");

        for (SqlFun<T, ?> column : columns) {
            typedThis.getFunFieldName(column, sqlColumn -> {
                stringBuilder.append(sqlColumn.getTableName()).append(".").append(sqlColumn.getColumnName()).append(",");
            });
        }

        orderBySql = stringBuilder.substring(0, stringBuilder.length() - 1) + " DESC";
        return children;
    }

    public final LambdaQueryWrapper<T> ORDER_BY_DESC(boolean condition, SqlFun<T, ?>... columns) {
        if (condition) {
            ORDER_BY_DESC(columns);
        }
        return children;
    }


    //group by
    public final LambdaQueryWrapper<T> GROUP_BY(SqlFun<T, ?>... columns) {
        StringBuilder stringBuilder = new StringBuilder("GROUP BY ");

        for (SqlFun<T, ?> column : columns) {
            typedThis.getFunFieldName(column, sqlColumn -> {
                stringBuilder.append(sqlColumn.getTableName()).append(".").append(sqlColumn.getColumnName()).append(",");
            });
        }

        groupBySql = stringBuilder.substring(0, stringBuilder.length() - 1);
        return children;
    }

    public final LambdaQueryWrapper<T> GROUP_BY(boolean condition, SqlFun<T, ?>... columns) {
        if (condition) {
            GROUP_BY(columns);
        }
        return children;
    }

    //having xx=%s and xx=%s
    public final LambdaQueryWrapper<T> HAVING(String sqlHaving, Object... params) {
        if (sqlHaving == null || sqlHaving.isEmpty()) {
            throw new IllegalArgumentException("having sql is empty");
        }
        havingSql = "HAVING " + String.format(sqlHaving, params);
        return children;
    }

    public final LambdaQueryWrapper<T> HAVING(boolean condition, String sqlHaving, Object... params) {
        if (condition) {
            HAVING(sqlHaving, params);
        }
        return children;
    }

    //LIMIT
    public final LambdaQueryWrapper<T> LIMIT(int limit, int offset) {
        if (limit < 0 || offset < 0) {
            throw new IllegalArgumentException("limit limit or offset is error");
        }
        limitSql = "LIMIT " + limit + " OFFSET " + offset;
        return children;
    }

    public final LambdaQueryWrapper<T> LIMIT(int num) {
        if (num < 0) {
            throw new IllegalArgumentException("limit num is error");
        }
        limitSql = "LIMIT " + num;
        return children;
    }


    @Override
    public String getSqlSegment() {
        String sqlSegment = super.getSqlSegment();
        return handle(sqlSegment);
    }

    @Override
    public String sql() {
        String sql = super.sql();
        return handle(sql);
    }

    private String handle(String sql) {
        //如果有 group by 则加上
        if (groupBySql != null) {
            sql = sql + "\n" + groupBySql;
        }

        //如果有 having 则加上
        if (havingSql != null) {
            sql = sql + "\n" + havingSql;
        }

        //如果有 order by 则加上
        if (orderBySql != null) {
            sql = sql + "\n" + orderBySql;
        }
        //如果有 limit 则加上
        if (limitSql != null) {
            //如果結尾是WHERE那么就去掉
            if (sql.endsWith("WHERE")) {
                sql = sql.substring(0, sql.length() - 6);
            }
            sql = sql + "\n" + limitSql;
        }
        return sql;
    }

}
